﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows.Forms;

namespace Class2Table
{
	public partial class MainForm : Form
	{
		private readonly Dictionary<string, string> _dic = new Dictionary<string, string>
		                                                   	{
		                                                   		{typeof (int).Name.ToUpper(), "[int]"},
		                                                   		{typeof (float).Name.ToUpper(), "[float]"},
		                                                   		{typeof (double).Name.ToUpper(), "[double]"},
		                                                   		{typeof (long).Name.ToUpper(), "[real]"},
		                                                   		{typeof (decimal).Name.ToUpper(), "[decimal](10, 0)"},
		                                                   		{typeof (bool).Name.ToUpper(), "[tinyint]"},
		                                                   		{typeof (string).Name.ToUpper(), "[varchar](255)"},
		                                                   		{typeof (DateTime).Name.ToUpper(), "[datetime]"},
		                                                   		{typeof (Image).Name.ToUpper(), "[image]"},
		                                                   		{typeof (Bitmap).Name.ToUpper(), "[image]"},
		                                                   		{typeof (object).Name.ToUpper(), "[sql_variant]"},
		                                                   	};

		public MainForm()
		{
			InitializeComponent();
			Text = string.Format("{0} v{1} [βeta]", Application.ProductName, Application.ProductVersion);
		}

		private void btnFile_Click(object sender, EventArgs e)
		{
			using (var d = new OpenFileDialog())
			{
				if (d.ShowDialog() != DialogResult.OK) return;

				txtFile.Text = d.FileName;
			}
		}

		private void txtFile_TextChanged(object sender, EventArgs e)
		{
			try
			{
				if (!File.Exists(txtFile.Text)) return;

				Assembly ass = Assembly.LoadFrom(txtFile.Text);
				if (ass == null) return;

				cmbTypes.DataSource = ass.GetTypes();
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message, "Error while loading assembly",
				                MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private void cmbTypes_SelectedIndexChanged(object sender, EventArgs e)
		{
			var type = cmbTypes.SelectedItem as Type;
			if (type == null) return;

			grdProps.DataSource = type.GetProperties();

			for (int i = 0; i < grdProps.Rows.Count; i++)
			{
				grdProps.Rows[i].Cells["colChk"].Value = true;
			}
		}

		private void btnSQL_Click(object sender, EventArgs e)
		{
			var type = cmbTypes.SelectedItem as Type;
			if (type == null || grdProps.Rows.Count < 1)
			{
				MessageBox.Show("Please select Type (Class) with Properties.", "Error while SQL generation",
				                MessageBoxButtons.OK, MessageBoxIcon.Error);
				return;
			}

			if (txtDB.Text.IsNullOrEmpty())
			{
				MessageBox.Show("Please enter DB name.", "Error while SQL generation",
				                MessageBoxButtons.OK, MessageBoxIcon.Error);
				return;
			}

			txtSQL.Clear();

			var sqlStr = new StringBuilder();
			sqlStr = sqlStr.AppendFormat("CREATE TABLE {0}\r\n(", type.Name);

			for (int i = 0; i < grdProps.Rows.Count; i++)
			{
				var prop = grdProps.Rows[i].DataBoundItem as PropertyInfo;
				if (prop == null || grdProps.Rows[i].Cells["colChk"].Value == null) continue;

				var selected = (bool) grdProps.Rows[i].Cells["colChk"].Value;
				if (!selected) continue;

				string col = ConvertProperty(prop);
				if (col.IsNullOrEmpty()) continue;

				sqlStr.AppendFormat("\r\n{0}{1}", col, i < grdProps.Rows.Count - 1 ? "," : string.Empty);
			}

			sqlStr.AppendFormat("\r\n)");

			txtSQL.Focus();
			txtSQL.Text = sqlStr.ToString();
		}

		private string ConvertProperty(PropertyInfo prop)
		{
			if (prop == null) return null;
			string key = prop.PropertyType.Name.ToUpper();
			string colType = _dic.ContainsKey(key) ? _dic[key] : "[varchar](255)";
			return string.Format("[{0}] {1} NOT NULL", prop.Name, colType);
		}

		private void btnCreateTable_Click(object sender, EventArgs e)
		{
			try
			{
				UseWaitCursor = true;
				Enabled = false;

				btnSQL.PerformClick();

				var str = new SqlConnectionStringBuilder
				          	{
				          		DataSource = string.Format("{0}\\{1}", txtAddress.Text, txtEngine.Text),
				          		InitialCatalog = txtDB.Text,
				          		UserID = txtUsername.Text,
				          		Password = txtPassword.Text
				          	};

				using (var con = new SqlConnection(str.ToString()))
				{
					con.Open();

					using (var cmd = new SqlCommand(txtSQL.Text, con))
					{
						cmd.ExecuteNonQuery();
					}

					con.Close();
				}

				MessageBox.Show("The table was successfully created.", "Table creation",
				                MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message, "Error while table creation",
				                MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
			finally
			{
				Enabled = true;
				UseWaitCursor = false;
			}
		}
	}
}